package nsalt.arch 

import chisel3._
import chisel3.util._

import nsalt._

object RV32MInstr extends InstrType with Config {
  def MUL     = BitPat("b0000001_?????_?????_000_?????_0110011")
  def MULH    = BitPat("b0000001_?????_?????_001_?????_0110011")
  def MULHSU  = BitPat("b0000001_?????_?????_010_?????_0110011")
  def MULHU   = BitPat("b0000001_?????_?????_011_?????_0110011")
  def DIV     = BitPat("b0000001_?????_?????_100_?????_0110011")
  def DIVU    = BitPat("b0000001_?????_?????_101_?????_0110011")
  def REM     = BitPat("b0000001_?????_?????_110_?????_0110011")
  def REMU    = BitPat("b0000001_?????_?????_111_?????_0110011")
  def MULW    = BitPat("b0000001_?????_?????_000_?????_0111011")
  def DIVW    = BitPat("b0000001_?????_?????_100_?????_0111011")
  def DIVUW   = BitPat("b0000001_?????_?????_101_?????_0111011")
  def REMW    = BitPat("b0000001_?????_?????_110_?????_0111011")
  def REMUW   = BitPat("b0000001_?????_?????_111_?????_0111011")

  val mulTable = Array(
    MUL            -> List(InstrR, FuncType.mdu, MulDivOperType.mul),
    MULH           -> List(InstrR, FuncType.mdu, MulDivOperType.mulh),
    MULHSU         -> List(InstrR, FuncType.mdu, MulDivOperType.mulhsu),
    MULHU          -> List(InstrR, FuncType.mdu, MulDivOperType.mulhu)
  )
  val divTable = Array(
    DIV            -> List(InstrR, FuncType.mdu, MulDivOperType.div),
    DIVU           -> List(InstrR, FuncType.mdu, MulDivOperType.divu),
    REM            -> List(InstrR, FuncType.mdu, MulDivOperType.rem),
    REMU           -> List(InstrR, FuncType.mdu, MulDivOperType.remu)
  )
  val table = mulTable ++ (if (DIV_SUPPORT) divTable else Array())
}

object RV64MInstr extends InstrType with Config {
  def MULW    = BitPat("b0000001_?????_?????_000_?????_0111011")
  def DIVW    = BitPat("b0000001_?????_?????_100_?????_0111011")
  def DIVUW   = BitPat("b0000001_?????_?????_101_?????_0111011")
  def REMW    = BitPat("b0000001_?????_?????_110_?????_0111011")
  def REMUW   = BitPat("b0000001_?????_?????_111_?????_0111011")

  val mulTable = Array(
    MULW           -> List(InstrR, FuncType.mdu, MulDivOperType.mulw)
  )
  val divTable = Array(
    DIVW           -> List(InstrR, FuncType.mdu, MulDivOperType.divw),
    DIVUW          -> List(InstrR, FuncType.mdu, MulDivOperType.divuw),
    REMW           -> List(InstrR, FuncType.mdu, MulDivOperType.remw),
    REMUW          -> List(InstrR, FuncType.mdu, MulDivOperType.remuw)
  )
  val table = mulTable ++ (if (DIV_SUPPORT) divTable else Array())
}

object RVMInstr extends Config {
  val table = RV32MInstr.table ++ (if (DATA_BITS == 64) RV64MInstr.table else Array())
}
